package cn.luna.service.impl;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import cn.luna.service.BaseService;
public abstract class BaseServiceImpl<T> implements BaseService<T> {
	@PersistenceContext
	protected EntityManager em;
	@SuppressWarnings("unchecked")
	protected Class<T> entityClass = (Class<T>) getSuperClassGenricType(this.getClass());
	private static Class<?> getSuperClassGenricType(Class<?> clazz) {
		Type genType = clazz.getGenericSuperclass();
		if (!(genType instanceof ParameterizedType)) {
			return Object.class;
		}
		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
		if (!(params[0] instanceof Class)) {
			return Object.class;
		}
		return (Class<?>) params[0];
	}
	@Transactional
	@Override
	public void save(T entity) {
		em.persist(entity);
	}
	@Transactional
	@Override
	public void update(T entity) {
		em.merge(entity);
	}
	@Transactional
	@Override
	public void delete(Serializable... ids) {
		for (Serializable id : ids) {
			em.remove(em.getReference(entityClass, id));
		}
	}
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	@Override
	public T findById(Serializable id) {
		return em.find(entityClass, id);
	}
	@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
	@Override
	public List<T> findByJpql(String jpql, int firstResult, int maxResult,Object... objects) {
		TypedQuery<T> query= em.createQuery(jpql, entityClass);
		if(objects!=null && objects.length>0){
			int len=objects.length;
			for(int i=0;i<len;i++){
				query.setParameter(i, objects[i]);
			}
		}
		return query.setFirstResult(firstResult).setMaxResults(maxResult).getResultList();
	}
}
